﻿
/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A
 * copy of the license can be found at http://go.microsoft.com/fwlink/?LinkID=131993. If
 * you cannot locate the Microsoft Public License, please send an email to
 * mixon@microsoft.com. By using this source code in any fashion, you are agreeing to
 * be bound by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 *
 * ***************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Xml.Linq;
using System.IO;
using System.Xml;

namespace MIXOnline.Descry.Controls
{
    /*
     * This sample shows 2 things:
     * 1. It shows how to load an XML file and parse it using XLINQ
     * 2. It demonstrates a simple overriding of the default look/behavior of the TreeMapItem leaf nodes.
     */
    public partial class Page : UserControl
    {
        Random r = new Random(1);
        List<Color> colors = new List<Color>() { Colors.Blue, Colors.Brown, Colors.Cyan, Colors.Green, Colors.Magenta, Colors.Orange, Colors.Purple, Colors.Red, Colors.Yellow, Colors.LightGray, Colors.Gray };

        public Page()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Page_Loaded);
        }

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            LoadXmlFile("SellerList.xml");
        }

        /// <summary>
        /// Load a file and fire an event when it's loaded.
        /// </summary>
        /// <param name="filename">Path to the file</param>
        private void LoadXmlFile(string filename)
        {
            WebClient client = new WebClient();
            client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(XMLFileLoaded);
            client.DownloadStringAsync(new Uri(filename, UriKind.RelativeOrAbsolute));
        }

        void XMLFileLoaded(object sender, DownloadStringCompletedEventArgs e)
        {
            // if this causes an error it is most likely that the file cannot be found.
            if (e.Error == null) 
            {
                string data = e.Result;

                // Tbe XML Tree expected is in a format where a <Node> contains a <Name> and <Value> element 
                // as strings, and a <Nodes> element which contains zero or more <Node> elements
                XElement topNode = XElement.Load(GetXmlReaderFromString(data));

                TreeMapItem root = new TreeMapItem(); // create a root container

                GenerateTreeMap(root, topNode); // walk the XML and create a TreeMapItem hierarchy under the root container

                TreeMapControl.LoadTreeMap(root); // pass the TreeMapItem hierarchy to the TreeMapControl
            }
        }

        /// <summary>
        /// This function walks and XML file and creates and populates TreeMapItems with XML node values.
        /// It will also walks the XML hierarchy recursively if one exists.
        /// </summary>
        /// <param name="ti">The current TreeMapItem that is being operated on</param>
        /// <param name="currentNode">The current XML node that is being used to populate TreeMapItem properties</param>
        private void GenerateTreeMap(TreeMapItem ti, XElement currentNode)
        {
            // Grab child nodes for this node if there are any and find out how many there are.
            //
            XElement nodes = currentNode.Element("Nodes");

            int subnodeCount = 0;
            IEnumerable<XElement> subnodes = null;

            if (nodes != null)
            {
                subnodes = nodes.Elements("Node");
                subnodeCount = subnodes.Count();
            }

            string name = string.Empty;
            string state = string.Empty;
            long size = 1;

            // grab the node name, value and state
            if (currentNode.Element("Name") != null && !currentNode.Element("Name").IsEmpty)
                name = currentNode.Element("Name").Value;

            if (currentNode.Element("Value") != null && !currentNode.Element("Value").IsEmpty)
                size = long.Parse(currentNode.Element("Value").Value);

            if (currentNode.Element("xstate") != null && !currentNode.Element("xstate").IsEmpty)
                state = currentNode.Element("xstate").Value;


            // if there are no children nodes create a TreeMapItem leaf node
            if (subnodeCount == 0) 
            {
                ti.Children.Add(new TreeMapItem() 
                { 
                    Label = state + " - " + name + ": $" + size / 1000000 + " M", 
                    Size = size,

                    // This causes the Custom look/feel of a TreeMapItem defined in the CustomTreeMapItem class.
                    // Note that not all the same UI needs to be rendered for all TreeMapItems.
                    PanelItemType = typeof(CustomTreeMapItem) 
                });
            }
            else // if there are subnodes create a TreeMapItem as a container node
            {
                // choose a random color that will act as the background color for leaf nodes
                TreeMapItem treemap = new TreeMapItem() 
                { 
                    Color = colors[r.Next(9)], 
                    Size = size, 
                    PanelItemType = typeof(CustomTreeMapItem) 
                };

                ti.Children.Add(treemap);

                // keep walking the hierarchy recursively
                for (int count = 0; count < subnodes.Count(); count++)
                {
                    GenerateTreeMap(treemap, subnodes.ElementAt(count));
                }
            }
        }

        /// <summary>
        /// Helper function that loads an XML string into an XmlReader
        /// </summary>
        /// <param name="xml">Any valid XML as a string</param>
        /// <returns></returns>
        private XmlReader GetXmlReaderFromString(string xml)
        {
            StringReader sr = new StringReader(xml);
            XmlReaderSettings settings = new XmlReaderSettings();
            return XmlReader.Create(sr, settings);
        }

    }
}
